import java.awt.CardLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import edu.jhu.tcj.purfuit.Category;
import edu.jhu.tcj.purfuit.CategoryManager;
import edu.jhu.tcj.purfuit.Game;
import edu.jhu.tcj.purfuit.Question;
import edu.jhu.tcj.purfuit.QuestionFactory;
import edu.jhu.tcj.purfuit.Turn.TurnState;
import edu.jhu.tcj.purfuit.utils.GameFile;
import edu.jhu.tcj.purfuit.view.ManageCatView;
import edu.jhu.tcj.purfuit.view.ManageQuesView;

public class Application extends JFrame {

	public static final String LOGO_PANEL = "LOGO_PANEL";
	public static final String SELECTION_PANEL = "SELECTION_PANEL";
	public static final String PLAYER_SETUP_PANEL = "PLAYER_SETUP_PANEL";
	public static final String GAMEBOARD_PANEL = "GAMEBOARD_PANEL";
	public static final String QUESTION_PANEL = "QUESTION_PANEL";
	public static final String INCORRECT_PANEL = "INCORRECT_PANEL";
	public static final String CORRECT_PANEL = "CORECT_PANEL";
	public static final String ENDGAME_PANEL = "ENDGAME_PANEL";
	
	private GamePanel active;
	
	private CardLayout cardLayout = new CardLayout();
	private JPanel cards = new JPanel(cardLayout);
	private JMenuBar menuBar = new JMenuBar();

	private SoundManager soundManager = new SoundManager();

	private LogoPanel logoPanel;
	private SelectionPanel selectionPanel;
	private PlayerSetupPanel playerSetupPanel;
	private GameBoardPanel gameBoardPanel;
	private QuestionPanel questionPanel;
	private IncorrectPanel incorrectPanel;
	private CorrectPanel correctPanel;
	private EndGamePanel endGamePanel;
	private Category[] categories;
	private QuestionFactory factory;
	private JMenuItem saveAction;
	private Game saveActionGame = null;

	public Application() throws FileNotFoundException, IOException {
		super("Trivial Purfuit");

		categories = CategoryManager.getInstance().getCategories();
		factory = QuestionFactory.getInstance(new File("conf/Questions"));
		
		logoPanel = new LogoPanel(this, soundManager);
		selectionPanel = new SelectionPanel(this, soundManager);
		playerSetupPanel = new PlayerSetupPanel(this, soundManager);
		gameBoardPanel = new GameBoardPanel(this, soundManager);
		incorrectPanel = new IncorrectPanel(this);
		correctPanel = new CorrectPanel(this);
		endGamePanel = new EndGamePanel(this);
		questionPanel = new QuestionPanel(soundManager);
		
		addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent ke) {
				active.keyPressed(ke);
			}
		});

		addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				active.mouseClicked(e);
			}
		});

		addMouseMotionListener(new MouseMotionAdapter() {
			public void mouseMoved(MouseEvent e) {
				active.mouseMoved(e);
			}
		});

		getContentPane().add(cards);

		menuBar.setVisible(false);

		active = logoPanel;

		cards.add(logoPanel, LOGO_PANEL);
		cards.add(selectionPanel, SELECTION_PANEL);
		cards.add(playerSetupPanel, PLAYER_SETUP_PANEL);
		cards.add(gameBoardPanel, GAMEBOARD_PANEL);
		cards.add(questionPanel, QUESTION_PANEL);
		cards.add(incorrectPanel, INCORRECT_PANEL);
		cards.add(correctPanel, CORRECT_PANEL);
		cards.add(endGamePanel, ENDGAME_PANEL);

		showLogoPanel();
		
		// Creates a menubar for a JFrame

		// Add the menubar to the frame
		setJMenuBar(menuBar);
		menuBar.setVisible(false);

		// Define and add two drop down menu to the menubar
		JMenu fileMenu = new JMenu("File");
		menuBar.add(fileMenu);

		// Create and add simple menu item to one of the drop down menu
		JMenuItem newAction = new JMenuItem("New Game");
		newAction.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, java.awt.Event.CTRL_MASK));

		saveAction = new JMenuItem("Save Game");
		saveAction.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, java.awt.Event.CTRL_MASK));

		saveAction.setEnabled(false);
		JMenuItem loadAction = new JMenuItem("Load Game");
		loadAction.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, java.awt.Event.CTRL_MASK));

		loadAction.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				JFileChooser fileChooser = new JFileChooser();
				int returnVal = fileChooser.showOpenDialog(null);
		        if (returnVal == JFileChooser.APPROVE_OPTION) {
		            File file = fileChooser.getSelectedFile();
		            System.out.println("Opening: " + file.getName() + ".");
					try {
						GameFile gf = new GameFile();
						Game loadedGame = gf.loadGame(file.getPath());
						showGameBoardPanel(loadedGame);
					} catch (Exception e1) {
						e1.printStackTrace();
						JOptionPane.showMessageDialog(null, "Unable to load game");
					}
		        } else {
		        	System.out.println("Save command cancelled by user.");
		        }
		        fileChooser.setVisible(false);
				
				

			}
		});
		JMenuItem exitAction = new JMenuItem("Exit");
		exitAction.setAccelerator(KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, java.awt.Event.CTRL_MASK));

		JCheckBoxMenuItem soundsMenuItem = new JCheckBoxMenuItem("Mute Sounds");
		soundsMenuItem.setSelected(soundManager.isMuted());
		
		
		fileMenu.add(newAction);
		fileMenu.add(saveAction);
		fileMenu.add(loadAction);
		fileMenu.addSeparator();
		fileMenu.add(soundsMenuItem);
		fileMenu.addSeparator();
		fileMenu.add(exitAction);

		JMenu configMenu = new JMenu("Configuration");
		JMenuItem configCategories = new JMenuItem("Configure Categories");
		configCategories.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				//JOptionPane.showMessageDialog(Application.this, new ManageCatView(categories));
				ManageCatView view = new ManageCatView(categories);
			}
		});
		configMenu.add(configCategories);
		
		JMenuItem configQuestions = new JMenuItem("Configure Questions");
		configQuestions.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				
				Map<Category, List<Question>> allQuestions = factory.getAllQuestions();
				List<Question> questionList = new ArrayList<Question>();
				for (Category cat : allQuestions.keySet()) {
					questionList.addAll(allQuestions.get(cat));
				}
				Question[] questions = questionList.toArray(new Question[]{});
				
				ManageQuesView view = new ManageQuesView(questions, categories);
				
				//JOptionPane.showMessageDialog(Application.this,view);
			}
		});
		configMenu.add(configQuestions);
		
		menuBar.add(configMenu);
		
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent f) {
				exitApplication();
			}
		});

		soundsMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				soundManager.toggleSound();
			}
		});
		exitAction.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent f) {
				exitApplication();
			}
		});
		newAction.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				showSelectionPanel();
			}
		});
	}

	public void showGameBoardPanel(final Game game) {
		gameBoardPanel.setGame(game);
		questionPanel.setGame(game);
		active = gameBoardPanel;
		saveAction.setEnabled(true);
		if (saveActionGame != game) {
			ActionListener[] actionListeners = saveAction.getActionListeners();
			for (ActionListener listener : actionListeners) {
				saveAction.removeActionListener(listener);
			}
			saveAction.addActionListener(new ActionListener() {
				
				@Override
				public void actionPerformed(ActionEvent arg0) {
					game.saveGame();
				}
			});
		}
		cardLayout.show(cards, GAMEBOARD_PANEL);
//		soundManager.playSelectNoise();
//		gameBoardPanel.timeline.play();
		if(game.getTurn().getTurnState().equals(TurnState.WaitingToAnswerQuestion)){
			showQuestionPanel(game.getTurn().getCurrentQuestion());
		}
	}
	
	public void showPlayerSetupPanel() {
		active = playerSetupPanel;
		cardLayout.show(cards, PLAYER_SETUP_PANEL);
//		soundManager.playSelectNoise();
	}
	
	public void showLogoPanel() {
		active = logoPanel;
		cardLayout.show(cards, LOGO_PANEL);
	}
	
	public void showQuestionPanel(Question question) {
		active = questionPanel;
		soundManager.diceRoll();
		questionPanel.updateQuestion(question);
//		questionPanel.timeline.play();
		cardLayout.show(cards, QUESTION_PANEL);
		
		
	}
	
	public void showEndGamePanel(Game game){
		endGamePanel.setGame(game);
		soundManager.pcmFilePlayer.stop();
		soundManager.winGame();
		active = endGamePanel;
		cardLayout.show(cards, ENDGAME_PANEL);
	}
	
	public void showSelectionPanel() {
		menuBar.setVisible(true);		
		active = selectionPanel;
		cardLayout.show(cards, SELECTION_PANEL);
	}
	
	public void ShowIncorrectPanel(Game game){
		active = incorrectPanel;
		incorrectPanel.setGame(game);
		soundManager.wrongAnswer();
		cardLayout.show(cards, INCORRECT_PANEL);
	}
	public void ShowCorrectPanel(Game game){
		active = correctPanel;
		correctPanel.setGame(game);
		soundManager.correctAnswer();
		cardLayout.show(cards, CORRECT_PANEL);
	}
	
	public void exitApplication() {
		soundManager.playExitSound();
		System.exit(0);
	}

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException, FileNotFoundException, IOException {
		UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

		final Application frame = new Application();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setSize(800, 600);
		frame.setVisible(true);
	}

	
}

